package com.alquimia.identityaccess.application.services;

import com.alquimia.identityaccess.application.events.user.*;
import com.alquimia.identityaccess.domain.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.UUID;

/**
 * Created by Ivo on 13/07/2014.
 */
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Transactional
    public UserRegisteredEvent registerUser(RegisterUserEvent aRegisterUserEvent) {

        Person person = new Person(
                new FullName(
                        aRegisterUserEvent.getFirstName(),
                        aRegisterUserEvent.getLastName()),
                new EmailAddress(aRegisterUserEvent.getEmailAddress())
        );

        UserId userId = userRepository.nextIdentity();

        User user = new User(
                userId,
                aRegisterUserEvent.getUsername(),
                aRegisterUserEvent.getPassword(),
                person
        );

        userRepository.create(user);

        return new UserRegisteredEvent(user);
    }

    @Transactional(readOnly = true)
    public UserAuthenticatedEvent authenticateUser(AuthenticateUserEvent aAuthenticateUserEvent) {


        User user = userRepository.userWithCredentials(
                aAuthenticateUserEvent.getUsername(),
                aAuthenticateUserEvent.getPassword());

        if (user == null)
            return UserAuthenticatedEvent.notFound(aAuthenticateUserEvent.getUsername());

        return new UserAuthenticatedEvent(user);

    }

    @Transactional
    public UserEmailAddressUpdatedEvent changeEmailAddress(UpdateEmailAddressEvent aUpdateEmailAddressEvent) {

        User user = userRepository.userOfId(
                new UserId(UUID.fromString(aUpdateEmailAddressEvent.getUserId()))
        );

        if (user == null)
            return UserEmailAddressUpdatedEvent.notFound(
                    aUpdateEmailAddressEvent.getUserId());

        EmailAddress emailAddress = new EmailAddress(
                aUpdateEmailAddressEvent.getEmailAddress());
        user.changeEmailAddress(emailAddress);

        userRepository.update(user);

        return new UserEmailAddressUpdatedEvent(user);
    }

    @Transactional
    public UserPersonalNameUpdatedEvent changeUserPersonalName(UpdateUserPersonalNameEvent aUpdateUserPersonalNameEvent) {


        User user = userRepository.userOfId(
                new UserId(UUID.fromString(aUpdateUserPersonalNameEvent.getUserId()))
        );

        if (user == null)
            return UserPersonalNameUpdatedEvent.notFound(
                    aUpdateUserPersonalNameEvent.getUserId());

        FullName fullName = new FullName(
                aUpdateUserPersonalNameEvent.getFirstName(),
                aUpdateUserPersonalNameEvent.getLastName());

        user.changeFullName(fullName);

        userRepository.update(user);

        return new UserPersonalNameUpdatedEvent(user);
    }

    @Transactional
    public UserPasswordUpdatedEvent changeUserPassword(UpdateUserPasswordEvent aUpdateUserPasswordEvent) {

        User user = userRepository.userOfId(
                new UserId(UUID.fromString(aUpdateUserPasswordEvent.getUserId()))
        );

        if (user == null)
            return UserPasswordUpdatedEvent.notFound(
                    aUpdateUserPasswordEvent.getUserId());

        if (!user.password().equals(aUpdateUserPasswordEvent.getCurrentPassword()))
            return UserPasswordUpdatedEvent.notFound(
                    aUpdateUserPasswordEvent.getUserId());

        user.changePassword(aUpdateUserPasswordEvent.getChangedPassword());

        userRepository.update(user);


        return new UserPasswordUpdatedEvent(user);
    }

    @Transactional(readOnly = true)
    public UserEvent user(RequestUserEvent aRequestUserEvent) {

        User user = userRepository.userOfId(
                new UserId(UUID.fromString(aRequestUserEvent.getUserId()))
        );

        if (user == null)
            return UserEvent.notFound(
                    aRequestUserEvent.getUserId());

        return new UserEvent(user);
    }


}
